﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ReadeAssetManager
{
    public partial class ucSearch : UserControl
    {
        private AMSServiceRef.User _user;

        private const string STR_ASSETS = "Assets";
        private const string STR_IMAGES = "Images";
        private const string STR_PURCH = "Purchases";
        private const string STR_SCHED = "Schedules";
        private const string STR_SERV = "Services";
        private const string STR_WARR = "Warranties";
        private const string STR_NONE = "No Assets Available";
        private const string STR_LOGGED_OUT = "Not Logged In";

        private enum _dlgopts { assets, purch, sched, serv, warr, images};
        private delegateReturnObject _returnobj;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="UserObj">[AMSServiceRef.User] The User object representing the current application user.</param>
        /// <param name="ReturnObjectMethod">[delegateReturnObject] A delegate method from frmMain invoked by Search().</param>
        public ucSearch(AMSServiceRef.User UserObj, delegateReturnObject ReturnObjectMethod)
        {
            _user = UserObj;
            _returnobj = ReturnObjectMethod;
            InitializeComponent();
            if (_user != null)
            {
                LoadSearchOptions();
                if (_user.Assets.Count > 0)
                    cmbSearch.Text = STR_ASSETS;
            }
            else
                cmbSearch.Items.Add(STR_LOGGED_OUT);
        }

        /// <summary>
        /// LoadSearchOptions
        /// Populates the cmbSearch control with the available search options.  This method only loads
        /// a domain if at least one object exists for that domain.  In other words, if a user has never
        /// created a Warranty record for any assets, Warranty will not appear in the list.
        /// </summary>
        private void LoadSearchOptions()
        {
            Dictionary<Type, string> lst = new Dictionary<Type, string>();
            foreach (AMSServiceRef.Asset asset in _user.Assets)
            {
                if (!lst.ContainsKey(typeof(AMSServiceRef.Asset)))
                    lst.Add(typeof(AMSServiceRef.Asset), STR_ASSETS);

                if (asset.Images.Count > 0 && !lst.ContainsKey(typeof(AMSServiceRef.AMSImage)))
                        lst.Add(typeof(AMSServiceRef.AMSImage), STR_IMAGES);

                if (asset.Purchases.Count > 0 && !lst.ContainsKey(typeof(AMSServiceRef.PurchaseData)))
                    lst.Add(typeof(AMSServiceRef.PurchaseData), STR_PURCH);

                if (asset.Schedules.Count > 0 && !lst.ContainsKey(typeof(AMSServiceRef.ScheduleData)))
                    lst.Add(typeof(AMSServiceRef.ScheduleData), STR_SCHED);

                if (asset.Services.Count > 0 && !lst.ContainsKey(typeof(AMSServiceRef.ServiceData)))
                    lst.Add(typeof(AMSServiceRef.ServiceData), STR_SERV);

                if (asset.Warranties.Count > 0 && !lst.ContainsKey(typeof(AMSServiceRef.WarrantyData)))
                    lst.Add(typeof(AMSServiceRef.WarrantyData), STR_WARR);
            }

            for (int i = 0; i < lst.Count; i++)
                cmbSearch.Items.Add(lst.Values.ElementAt<string>(i));

            if (cmbSearch.Items.Count == 0)
                cmbSearch.Items.Add(STR_NONE);
        }

        /// <summary>
        /// GetControlType
        /// Returns the type of the first control contained in the parent control.  Returns null if the Parent
        /// object has no children or does not possess a Controls property.  This method also exists on frmMain
        /// and serves essentially the same purpose.  Refactoring this method into a static Utility class might be
        /// appropriate.
        /// </summary>
        /// <param name="Parent">[Control] The parent control that contains this control.</param>
        /// <returns>[Type] The type of the first control in the Parent.Controls list.</returns>
        private Type GetControlType(Control Parent)
        {
            try
            {
                if (Parent.Controls.Count > 0)
                {
                    return Parent.Controls[0].GetType();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// LoadControl
        /// This method loads the search control as determined by the Options enumeration.
        /// </summary>
        /// <param name="Options">[_dlgopts] An enumeration of the available search domains.</param>
        private void LoadControl(_dlgopts Options)
        {
            switch (Options)
            {
                case _dlgopts.assets:
                    if (!(GetControlType(pnlSearchOpts) == typeof(ucSearchAsset)))
                    {
                        pnlSearchOpts.Controls.Clear();
                        ucSearchAsset srch = new ucSearchAsset(_user);
                        pnlSearchOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.images:
                    break;
                case _dlgopts.purch:
                    if (!(GetControlType(pnlSearchOpts) == typeof(ucSearchPurchase)))
                    {
                        pnlSearchOpts.Controls.Clear();
                        ucSearchPurchase srch = new ucSearchPurchase(_user);
                        pnlSearchOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.sched:
                    if (!(GetControlType(pnlSearchOpts) == typeof(ucSearchSchedule)))
                    {
                        pnlSearchOpts.Controls.Clear();
                        ucSearchSchedule srch = new ucSearchSchedule(_user);
                        pnlSearchOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.serv:
                    if (!(GetControlType(pnlSearchOpts) == typeof(ucSearchService)))
                    {
                        pnlSearchOpts.Controls.Clear();
                        ucSearchService srch = new ucSearchService(_user);
                        pnlSearchOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.warr:
                    if (!(GetControlType(pnlSearchOpts) == typeof(ucSearchWarranty)))
                    {
                        pnlSearchOpts.Controls.Clear();
                        ucSearchWarranty srch = new ucSearchWarranty(_user);
                        pnlSearchOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Search
        /// Retrieves the search results of the search control and passes it back to frmMain via
        /// the delegate.  The ISearchControl interface calls out the BuildAssetList method, which
        /// all domain search controls must implement.
        /// </summary>
        private void Search()
        {
            // Retrieve the asset list
            _returnobj(((ISearchControl)pnlSearchOpts.Controls[0]).BuildAssetList());
        }

        /// <summary>
        /// cmbSearch_TextChanged
        /// When the user selects a different search domain, this method loads the search control appropriate
        /// for that domain.
        /// </summary>
        /// <param name="sender">[object] The cmbSearch control.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a TextChanged event.</param>
        private void cmbSearch_TextChanged(object sender, EventArgs e)
        {
            switch (cmbSearch.Text)
            {
                case STR_ASSETS:
                    LoadControl(_dlgopts.assets);
                    break;
                case STR_IMAGES:
                    LoadControl(_dlgopts.images);
                    break;
                case STR_PURCH:
                    LoadControl(_dlgopts.purch);
                    break;
                case STR_SCHED:
                    LoadControl(_dlgopts.sched);
                    break;
                case STR_SERV:
                    LoadControl(_dlgopts.serv);
                    break;
                case STR_WARR:
                    LoadControl(_dlgopts.warr);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// btnSearch_Click
        /// When the user clicks the Search button, this method invokes the Search method.
        /// </summary>
        /// <param name="sender">[object] The btnSearch control.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void btnSearch_Click(object sender, EventArgs e)
        {
            Search();
        }
    }
}
